﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using io = System.IO;
using wf = System.Windows.Forms;
using System.Threading;

namespace editor.app
{
    /// <summary>
    /// ObjWindow.xaml 的交互逻辑
    /// </summary>
    public partial class ObjWindow : Window
    {
        comm.objst.DObject.Data _obj = null;
        string _fileName = "";
        string _sign = "";

        const string EXT_NAME = comm.objst.DObject.Data.FILE_EXT_NAME;

        public ObjWindow(string fileName = null)
        {
            InitializeComponent();
            this.LoadConfig1();

            if (fileName != null)
            {
                _fileName = fileName;
                OpenFile();
            }

            KeyDown += new KeyEventHandler(ObjWindow_KeyDown);
            btnNew.Click += new RoutedEventHandler(btnNew_Click);
            btnNewAction.Click += new RoutedEventHandler(btnNewAction_Click);
            btnNewActions.Click += new RoutedEventHandler(btnNewActions_Click);
            btnClearAction.Click += new RoutedEventHandler(btnClearAction_Click);
            btnReload.Click += new RoutedEventHandler(btnReload_Click);

            #region loop
            comm.ThreadHelper.Run(() =>
            {
                while (true)
                {
                    if (_obj != null)
                    {
                        var isChange = CheckSignChange();
                        Dispatcher.Invoke(new Action(() =>
                        {
                            Title = io.Path.GetFileName(_fileName) + (isChange ? "*" : "");
                        }));
                    }
                    Thread.Sleep(100);
                }
            });
            #endregion
        }

        void btnReload_Click(object sender, RoutedEventArgs e)
        {
            if (_fileName != null)
            {
                OpenFile();
            }
        }
        void btnClearAction_Click(object sender, RoutedEventArgs e)
        {
            _obj.ActionDic.Clear();
            Fill();
        }
        void btnNewActions_Click(object sender, RoutedEventArgs e)
        {
            var types = comm.objst.DObject.Data.GetActionTypes();
            foreach (var type in types)
            {
                if (!_obj.ActionDic.ContainsKey(type))
                {
                    _obj.ActionDic.Add(type, new comm.objst.ObjAction());
                }
            }
            Fill();
        }
        void btnNewAction_Click(object sender, RoutedEventArgs e)
        {
            _obj.ActionDic.Add(comm.GUID.NewString(), new comm.objst.ObjAction());
            Fill();
        }
        void ObjWindow_KeyDown(object sender, KeyEventArgs e)
        {
            if (Keyboard.Modifiers == ModifierKeys.Control)
            {
                if (e.Key == Key.S)
                {
                    SaveFile();
                }
            }
        }
        void btnNew_Click(object sender, RoutedEventArgs e)
        {
            var sfd = new wf.SaveFileDialog { Filter = EXT_NAME + "|*" + EXT_NAME };
            if (sfd.ShowDialog().ToString() == "OK")
            {
                _obj = new comm.objst.DObject.Data();
                _fileName = sfd.FileName;
                SaveFile();
                OpenFile();
            }
        }
        void btnDel_Click(object sender, RoutedEventArgs e)
        {
            var btn = (Button)sender;
            var parent = (FrameworkElement)((FrameworkElement)btn.Parent).Parent;
            _obj.ActionDic.Remove(parent.Tag.ToString());
            Fill();
        }
        void tbName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                var tb = (TextBox)sender;
                var parent = (FrameworkElement)((FrameworkElement)tb.Parent).Parent;
                var key = parent.Tag.ToString();
                if (!_obj.ActionDic.ContainsKey(tb.Text))
                {
                    var ac = _obj.ActionDic[key];
                    _obj.ActionDic.Remove(key);
                    _obj.ActionDic.Add(tb.Text, ac);
                    Fill();
                }
                else
                {
                    tb.Text = key;
                    tb.SelectAll();
                }
            }
        }
        void cbKeys_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var cb = (ComboBox)sender;
            var parent = (FrameworkElement)((FrameworkElement)cb.Parent).Parent;
            var key = parent.Tag.ToString();
            if (cb.SelectedIndex != -1)
            {
                var tb = (TextBlock)cb.SelectedValue;
                if (!_obj.ActionDic.ContainsKey(tb.Text))
                {
                    var ac = _obj.ActionDic[key];
                    _obj.ActionDic.Remove(key);
                    _obj.ActionDic.Add(tb.Text, ac);
                    Fill();
                }
                else
                {
                    int ix = 0, dix = -1;
                    foreach (var item in cb.Items)
                    {
                        var tb2 = (TextBlock)item;
                        if (tb2.Text == key)
                        {
                            dix = ix;
                        }
                        ix++;
                    }
                    cb.SelectedIndex = dix;
                }
            }
        }
        void tbTime_TextChanged(object sender, TextChangedEventArgs e)
        {
            var tb = (TextBox)sender;
            var parent = (FrameworkElement)tb.Parent;
            var key = parent.Tag.ToString();
            try
            {
                var ac = comm.JsonSerializer.Deserialize<comm.objst.ObjAction>(tb.Text);
                if (ac != null)
                {
                    _obj.ActionDic[key] = ac;
                }
            }
            catch (Exception)
            {
            }
        }

        void Fill()
        {
            spAction.Children.Clear();
            var types = comm.objst.DObject.Data.GetActionTypes();
            foreach (var key in _obj.ActionDic.Keys)
            {
                var item = _obj.ActionDic[key];
                var grid = new Grid
                {
                    Tag = key,
                    Margin = new Thickness(0, 0, 0, 4)
                };
                grid.Children.Add(new Border
                {
                    BorderBrush = new SolidColorBrush(Color2.Black(20)),
                    BorderThickness = new Thickness(0, 0, 0, 1)
                });

                var sp = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 0, 0, 4) };
                var btnDel = new Button { Content = "X", Width = 20, Margin = new Thickness(0, 0, 4, 0) };
                btnDel.Click += new RoutedEventHandler(btnDel_Click);

                var tbName = new TextBox { Text = key, Width = 120, Margin = new Thickness(0, 0, 4, 0) };
                tbName.KeyDown += new KeyEventHandler(tbName_KeyDown);

                var cbKeys = new ComboBox { Width = 120, Focusable = false, Margin = new Thickness(0, 0, 4, 0) };
                int ix = 0, dix = -1;
                foreach (var type in types)
                {
                    var tb = new TextBlock { Text = type };
                    if (type == key)
                    {
                        dix = ix;
                        tb.FontWeight = FontWeights.Bold;
                    }
                    cbKeys.Items.Add(tb);
                    ix++;
                }
                if (dix != -1)
                {
                    cbKeys.SelectedIndex = dix;
                }
                cbKeys.SelectionChanged += new SelectionChangedEventHandler(cbKeys_SelectionChanged);

                sp.Children.Add(btnDel);
                sp.Children.Add(tbName);
                sp.Children.Add(cbKeys);
                grid.Children.Add(sp);

                var tbTime = new TextBox { Text = comm.JsonSerializer.Serialize(item), Margin = new Thickness(276, 0, 0, 0) };
                tbTime.TextChanged += new TextChangedEventHandler(tbTime_TextChanged);
                grid.Children.Add(tbTime);

                spAction.Children.Add(grid);
            }
        }

        void SaveFile()
        {
            try
            {
                var bytes = comm.BinarySerializer.Serialize(_obj);
                io.File.WriteAllBytes(_fileName, bytes);
                MakeSign();
            }
            catch (Exception ex)
            {
                MessageBox.Show("save file:" + _fileName + " err!" + ex.Message);
            }
        }
        void OpenFile()
        {
            try
            {
                _obj = comm.BinarySerializer.Deserialize<comm.objst.DObject.Data>(io.File.ReadAllBytes(_fileName));
                MakeSign();
                Fill();
            }
            catch (Exception ex)
            {
                MessageBox.Show("open file:" + _fileName + " err!" + ex.Message);
            }
        }
        void MakeSign()
        {
            _sign = comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_obj));
        }
        bool CheckSignChange()
        {
            return _sign != comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_obj));
        }
    }
}
